package com.yhx.util;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

import com.yhx.config.handle.CustomPcapHandler;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;


/**
 * @Description:抓包工具类
 * @author:hutao
 * @mail:hutao_2017@aliyun.com
 * @date:2021年9月2日
 */
public class CaptureUtils {

	/**
	 * @Description:获取网络适配器,当返回List<PcapIf>为空时，说明未获取到网卡
	 * @author:hutao
	 * @mail:hutao_2017@aliyun.com
	 * @date:2021年9月2日
	 */
	public static List<PcapIf> getPcapIf() {
		StringBuilder errbuf = new StringBuilder();
		//定义网卡列表
		List<PcapIf> ifs = new ArrayList<PcapIf>();
		/* 返回值是一个整数结果代码，就像在 C 计数器部分一样。
		 * ifs 列表中填充了从 C 函数调用 findAllDevs 返回的相应 C 结构 pcap_if 链表中找到的所有网络设备。
		 */
		int statusCode = Pcap.findAllDevs(ifs, errbuf);
		if(statusCode != Pcap.OK){
			System.err.println("获取网卡失败：" + errbuf.toString());
		}
		return ifs;
	}

	/**
	 * @Description:开始捕获数据包
	 * @param
	 * @author:hutao
	 * @mail:hutao_2017@aliyun.com
	 * @date:2021年9月2日
	 */
	public static void capturePcap(PcapIf device) {
		//截断此大小的数据包
		int snaplen = Pcap.DEFAULT_JPACKET_BUFFER_SIZE;

		int promiscous = Pcap.MODE_PROMISCUOUS;

		//以毫秒为单位
		int timeout = 60 * 1000;
		//如果发生错误，它将保存一个错误字符串。 错误打开 Live 将返回 null
		StringBuilder errbuf = new StringBuilder();

		Pcap pcap = Pcap.openLive(device.getName(),snaplen,promiscous,timeout,errbuf);
		if(pcap == null) {
			System.err.println("获取数据包失败：" + errbuf.toString());
		}

		CustomPcapHandler<Object> handler = new CustomPcapHandler<Object>();
		// 捕获数据包计数
		int cnt = 1;
		//我们要发送到处理程序的自定义对象
		PrintStream out = System.out;
		while(true) {
			//每个数据包将被分派到抓包处理器Handler
			pcap.loop(cnt, handler, out);
		}
		//pcap.close();
	}
}
